package com.quan.sport.gateway.filter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.quan.common.base.bean.ResultBean;
import com.quan.common.utils.CommonUtils;
import com.quan.common.utils.JwtTokenUtils;
import com.quan.common.utils.RedisOperator;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;

@Component
public class TokenFilter extends ZuulFilter {

	private static Logger logger = LoggerFactory.getLogger(TokenFilter.class);

	@Autowired
	private RedisOperator redisOperator;

	/**
	 * JwtToken秘钥
	 */
	@Value("${jwt.secret:123456}")
	private String jwtSecret;

	/**
	 * JwtToken过去时间（秒）
	 */
	@Value("${jwt.timeout:1800}")
	private Long timeout;

	/**
	 * 不需要拦截的URI请求
	 */
	private static final String excludes = "((login$)|(/login)|(weixin))";

	@Override
	public boolean shouldFilter() { // 是否执行该过滤器，此处为true，说明需要过滤
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		String client = request.getHeader("APPCLIENT");
		
		//如果是微信浏览器则不执行当前过滤器
		if(CommonUtils.inWeixinBrowse(request) || StringUtils.isNotBlank(client)) {
			return false ;
		} else {
			return true; 
		}
	}

	@Override
	public int filterOrder() {
		return 10; // filter执行顺序，通过数字指定 ,优先级为0，数字越大，优先级越低
	}

	@Override
	public String filterType() {
		return "pre"; // 可以在请求被路由之前调用
	}

	@Override
	public Object run() throws ZuulException {
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		HttpServletResponse response = ctx.getResponse() ;
		response.setContentType("application/json; charset=utf-8");
		logger.info("TokenFilter：{} {}", request.getMethod(), request.getRequestURL().toString());
		
		//验证Token，判断用户是否登录
		if(!requestIsExclude(request) && !validToken(request)) {
			ctx.setSendZuulResponse(false);// 过滤该请求，不对其进行路由  
			ResultBean loginTimeOut = ResultBean.loginTimeOut();
			String message = JSON.toJSONString(loginTimeOut);
			ctx.setResponseBody(message);
			
			logger.debug("Token验证失败：状态[{}]，消息：{}", loginTimeOut.getStatus(), loginTimeOut.getMsg());
		}
		
		return null;
	}
	
	/**
	 * 验证登录Token
	 * @param request
	 * @return
	 */
	public boolean validToken(HttpServletRequest request) {
		String token = request.getHeader("Auth-Token");
		
		// Token为空
		if (null == token || "".equals(token.trim())) {
			return false;
		}
		
		Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
		if (null != parse) {
			Claims body = parse.getBody();
			boolean hasKey = this.redisOperator.hasKey("sso:token:" + body.get("userId"));
			if(hasKey) {
				this.redisOperator.expire("sso:token:" + body.get("userId"), timeout);
				return true ;
			} else {
				return false ;
			}
		} else {
			return false;
		}
	}
	
	/**
	 * 判定该URL是否需要拦截
	 * @param request
	 * @return
	 */
	private boolean requestIsExclude(HttpServletRequest request) {
		// 没有设定excludes是，所有经过filter的请求都需要被处理
		if (null == excludes || "".equals(excludes.trim())) {
			return false;
		}

		// 获取去除context path后的请求路径
		String contextPath = request.getContextPath();
		String uri = request.getRequestURI();
		uri = uri.substring(contextPath.length());

		Pattern p = Pattern.compile(excludes);
		Matcher m = p.matcher(uri);
		// 正则表达式匹配URI被排除，不需要拦截
		return m.find();
	}

}
